package com.vibeplayer.app.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * LRC格式歌词解析器
 */
public class LrcParser {

    // 时间标签正则表达式，支持[00:00.00]和[00:00:00]两种格式
    private static final Pattern TIME_PATTERN_1 = Pattern.compile("\\[(\\d{2}):(\\d{2})\\.(\\d{2})\\]");
    private static final Pattern TIME_PATTERN_2 = Pattern.compile("\\[(\\d{2}):(\\d{2}):(\\d{2})\\]");
    
    // 元数据标签正则表达式，如[ar:艺术家]
    private static final Pattern ID_TAG_PATTERN = Pattern.compile("\\[(\\w+):(.+?)\\]");
    
    private List<LrcEntry> lrcEntries = new ArrayList<>();
    private Map<String, String> metadata = new HashMap<>();
    private boolean isLoaded = false;
    private int currentLineIndex = 0;

    /**
     * 加载LRC歌词文件
     * @param lrcFile LRC文件
     * @return 是否加载成功
     */
    public boolean loadLrc(File lrcFile) {
        lrcEntries.clear();
        metadata.clear();
        isLoaded = false;
        currentLineIndex = 0;
        
        if (lrcFile == null || !lrcFile.exists()) {
            return false;
        }
        
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(lrcFile), "UTF-8"))) {
            return loadFromReader(reader);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }
    
    /**
     * 从URL加载LRC歌词
     * @param url 歌词URL
     * @return 是否加载成功
     */
    public boolean loadLrcFromUrl(String url) {
        lrcEntries.clear();
        metadata.clear();
        isLoaded = false;
        currentLineIndex = 0;
        
        try {
            URL lrcUrl = new URL(url);
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(lrcUrl.openStream(), "UTF-8"))) {
                return loadFromReader(reader);
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }
    
    /**
     * 从输入流加载LRC歌词
     * @param inputStream 输入流
     * @return 是否加载成功
     */
    public boolean loadLrcFromInputStream(InputStream inputStream) {
        lrcEntries.clear();
        metadata.clear();
        isLoaded = false;
        currentLineIndex = 0;
        
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"))) {
            return loadFromReader(reader);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }
    
    /**
     * 从字符串加载LRC歌词
     * @param lrcContent 歌词内容
     * @return 是否加载成功
     */
    public boolean loadLrcFromString(String lrcContent) {
        lrcEntries.clear();
        metadata.clear();
        isLoaded = false;
        currentLineIndex = 0;
        
        if (lrcContent == null || lrcContent.isEmpty()) {
            return false;
        }
        
        String[] lines = lrcContent.split("\\r?\\n");
        for (String line : lines) {
            parseLine(line);
        }
        
        // 按时间排序
        Collections.sort(lrcEntries, (o1, o2) -> (int) (o1.time - o2.time));
        
        isLoaded = !lrcEntries.isEmpty();
        return isLoaded;
    }
    
    /**
     * 从BufferedReader加载LRC歌词
     * @param reader BufferedReader
     * @return 是否加载成功
     */
    private boolean loadFromReader(BufferedReader reader) throws IOException {
        String line;
        while ((line = reader.readLine()) != null) {
            parseLine(line);
        }
        
        // 按时间排序
        Collections.sort(lrcEntries, (o1, o2) -> (int) (o1.time - o2.time));
        
        isLoaded = !lrcEntries.isEmpty();
        return isLoaded;
    }
    
    /**
     * 解析一行歌词
     * @param line 歌词行
     */
    private void parseLine(String line) {
        // 尝试解析元数据标签
        Matcher idTagMatcher = ID_TAG_PATTERN.matcher(line);
        if (idTagMatcher.matches()) {
            String key = idTagMatcher.group(1).toLowerCase();
            String value = idTagMatcher.group(2);
            metadata.put(key, value);
            return;
        }
        
        // 尝试解析时间标签
        boolean hasTimeTag = false;
        
        // 尝试第一种时间格式 [00:00.00]
        Matcher matcher1 = TIME_PATTERN_1.matcher(line);
        while (matcher1.find()) {
            hasTimeTag = true;
            int minutes = Integer.parseInt(matcher1.group(1));
            int seconds = Integer.parseInt(matcher1.group(2));
            int milliseconds = Integer.parseInt(matcher1.group(3)) * 10;
            
            long time = minutes * 60 * 1000 + seconds * 1000 + milliseconds;
            
            String text = line.substring(matcher1.end());
            // 移除其他时间标签
            text = text.replaceAll("\\[\\d{2}:\\d{2}\\.\\d{2}\\]", "");
            text = text.replaceAll("\\[\\d{2}:\\d{2}:\\d{2}\\]", "");
            
            if (!text.isEmpty()) {
                lrcEntries.add(new LrcEntry(time, text));
            }
        }
        
        // 如果第一种格式没有匹配，尝试第二种时间格式 [00:00:00]
        if (!hasTimeTag) {
            Matcher matcher2 = TIME_PATTERN_2.matcher(line);
            while (matcher2.find()) {
                int minutes = Integer.parseInt(matcher2.group(1));
                int seconds = Integer.parseInt(matcher2.group(2));
                int hundredths = Integer.parseInt(matcher2.group(3));
                
                long time = minutes * 60 * 1000 + seconds * 1000 + hundredths * 10;
                
                String text = line.substring(matcher2.end());
                // 移除其他时间标签
                text = text.replaceAll("\\[\\d{2}:\\d{2}\\.\\d{2}\\]", "");
                text = text.replaceAll("\\[\\d{2}:\\d{2}:\\d{2}\\]", "");
                
                if (!text.isEmpty()) {
                    lrcEntries.add(new LrcEntry(time, text));
                }
            }
        }
    }
    
    /**
     * 根据当前播放位置获取对应的歌词
     * @param time 当前播放位置（毫秒）
     * @return 当前歌词
     */
    public String getLyricLine(long time) {
        if (!isLoaded || lrcEntries.isEmpty()) {
            return "";
        }
        
        int index = findLyricIndex(time);
        if (index >= 0 && index < lrcEntries.size()) {
            currentLineIndex = index;
            return lrcEntries.get(index).text;
        }
        
        return "";
    }
    
    /**
     * 获取前一行歌词
     * @param time 当前播放位置（毫秒）
     * @return 前一行歌词，如果没有则返回空字符串
     */
    public String getPreviousLyricLine(long time) {
        if (!isLoaded || lrcEntries.isEmpty()) {
            return "";
        }
        
        int index = findLyricIndex(time);
        if (index > 0) {
            return lrcEntries.get(index - 1).text;
        }
        
        return "";
    }
    
    /**
     * 获取后一行歌词
     * @param time 当前播放位置（毫秒）
     * @return 后一行歌词，如果没有则返回空字符串
     */
    public String getNextLyricLine(long time) {
        if (!isLoaded || lrcEntries.isEmpty()) {
            return "";
        }
        
        int index = findLyricIndex(time);
        if (index >= 0 && index < lrcEntries.size() - 1) {
            return lrcEntries.get(index + 1).text;
        }
        
        return "";
    }
    
    /**
     * 获取下一行歌词的时间
     * @param time 当前播放位置（毫秒）
     * @return 下一行歌词的时间，如果没有则返回-1
     */
    public long getNextLyricTime(long time) {
        if (!isLoaded || lrcEntries.isEmpty()) {
            return -1;
        }
        
        int index = findLyricIndex(time);
        if (index >= 0 && index < lrcEntries.size() - 1) {
            return lrcEntries.get(index + 1).time;
        }
        
        return -1;
    }
    
    /**
     * 根据时间查找歌词索引
     * @param time 时间（毫秒）
     * @return 歌词索引，如果未找到返回-1
     */
    public int findLyricIndex(long time) {
        if (!isLoaded || lrcEntries.isEmpty()) {
            return -1;
        }
        
        // 如果时间小于第一条歌词的时间
        if (time < lrcEntries.get(0).time) {
            return -1;
        }
        
        // 如果时间大于最后一条歌词的时间
        if (time >= lrcEntries.get(lrcEntries.size() - 1).time) {
            return lrcEntries.size() - 1;
        }
        
        // 二分查找
        int left = 0;
        int right = lrcEntries.size() - 1;
        
        while (left <= right) {
            int mid = (left + right) / 2;
            long midTime = lrcEntries.get(mid).time;
            
            if (time < midTime) {
                right = mid - 1;
            } else if (time > midTime) {
                left = mid + 1;
            } else {
                return mid;
            }
        }
        
        // 返回最接近的较小时间的歌词
        return right;
    }
    
    /**
     * 获取歌词元数据
     * @param key 元数据键
     * @return 元数据值，如果不存在则返回null
     */
    public String getMetadata(String key) {
        return metadata.get(key.toLowerCase());
    }
    
    /**
     * 获取所有歌词条目
     * @return 歌词条目列表
     */
    public List<LrcEntry> getLrcEntries() {
        return new ArrayList<>(lrcEntries);
    }
    
    /**
     * 获取所有元数据
     * @return 元数据映射
     */
    public Map<String, String> getAllMetadata() {
        return new HashMap<>(metadata);
    }
    
    /**
     * 获取歌词总行数
     * @return 歌词总行数
     */
    public int getLyricCount() {
        return lrcEntries.size();
    }
    
    /**
     * 是否已加载歌词
     * @return 是否已加载歌词
     */
    public boolean isLoaded() {
        return isLoaded;
    }
    
    /**
     * 清除已加载的歌词
     */
    public void clear() {
        lrcEntries.clear();
        metadata.clear();
        isLoaded = false;
        currentLineIndex = 0;
    }
    
    /**
     * 歌词条目类
     */
    public static class LrcEntry {
        public long time;
        public String text;
        
        public LrcEntry(long time, String text) {
            this.time = time;
            this.text = text;
        }
        
        @Override
        public String toString() {
            return "[" + formatTime(time) + "] " + text;
        }
        
        /**
         * 格式化时间
         * @param time 时间（毫秒）
         * @return 格式化的时间字符串
         */
        private String formatTime(long time) {
            long minutes = time / 60000;
            long seconds = (time % 60000) / 1000;
            long milliseconds = (time % 1000) / 10;
            return String.format("%02d:%02d.%02d", minutes, seconds, milliseconds);
        }
    }
} 